#pragma once

#include "zMatrixBase.hpp"

namespace zzz{
template<typename T,class Major>
class HCombineMatrixR : public zMatrixBaseR<T,Major>
{
public:
  explicit HCombineMatrixR(const zMatrixBaseR<T,Major> &mat1, const zMatrixBaseR<T,Major> &mat2)
    :mat1_(mat1),mat2_(mat2),zMatrixBaseR<T,Major>(mat1.rows_,mat1.cols_+mat2.cols_)
  {ZCHECK_EQ(mat1.rows_, mat2.rows_);}
  const T operator()(zuint r, zuint c) const
  {
    CheckRange(r, c);
    if (c<mat1_.cols_) return mat1_(r,c);
    else return mat2_(r,c-mat1_.cols_);
  }
private:
  const zMatrixBaseR<T,Major> &mat1_, &mat2_;
};

template<typename T,class Major>
const HCombineMatrixR<T,Major> operator,(const zMatrixBaseR<T,Major> &mat1, const zMatrixBaseR<T,Major> &mat2)
{return HCombineMatrixR<T,Major>(mat1,mat2);}

template<typename T,class Major>
class VCombineMatrixR : public zMatrixBaseR<T,Major>
{
public:
  explicit VCombineMatrixR(const zMatrixBaseR<T,Major> &mat1, const zMatrixBaseR<T,Major> &mat2)
    :mat1_(mat1),mat2_(mat2),zMatrixBaseR<T,Major>(mat1.rows_+mat2.rows_,mat1.cols_)
  {ZCHECK_EQ(mat1.cols_, mat2.cols_);}
  const T operator()(zuint r, zuint c) const
  {
    CheckRange(r, c);
    if (r<mat1_.rows_) return mat1_(r,c);
    else return mat2_(r-mat1_.rows_,c);
  }
private:
  const zMatrixBaseR<T,Major> &mat1_, &mat2_;
};

template<typename T,class Major>
const VCombineMatrixR<T,Major> operator%(const zMatrixBaseR<T,Major> &mat1, const zMatrixBaseR<T,Major> &mat2)
{return VCombineMatrixR<T,Major>(mat1,mat2);}
}
